package com.simple.mq.common.util;

/**
 * 参考rabbitMQ的匹配规则，对用户的键与队列的键进行匹配
 *
 * @author Mr_Hades
 * @date 2022-03-26 14:28
 */
public class KeyUtil {

    public static final String SYMBOL_STAR = "*";
    public static final String SYMBOL_JING = "#";

    /**<pre>
     * 匹配routingKey和bindingKey的工具类
     * 按照以下规则进行匹配：
     *  1. #：匹配一个或多个词
     *  2. *：匹配不多不少恰好1个词
     *  3. |：或的关系，用来匹配多个key
     * 举例：
     *      item.#：能够匹配item.insert.abc 或者 item.insert
     *      item.*：只能匹配item.insert
     * 注：  # 符号只能出现在开头或者结尾，不能出现多次
     *
     *</pre>
     * @return 是否匹配成功
     */
    public static boolean routingKeyCompare(String routingKey, String bindingKey) {
        String[] bindingKeys = bindingKey.split("\\|");
        String[] routingKeys = routingKey.split("\\.");
        for (String key : bindingKeys) {
            // item.* ==> ["item", "*"]
            String[] subKey = key.split("\\.");
            int len2 = subKey.length;
            int len1 = routingKeys.length;
            // 包含#的bindingKey
            if (key.contains(SYMBOL_JING)) {
                if (!checkOnlyOne(key)) {
                    return false;
                }
                int i;
                if (SYMBOL_JING.equals(subKey[0])) {
                    // 从后往前比
                    for (i = 1; i <= Math.min(len1, len2); i++) {
                        if (!subKey[len2 - i].equals(routingKeys[len1 - i])) {
                            break;
                        }
                    }
                    if (SYMBOL_JING.equals(subKey[len2 - i])) {
                        // 当前键匹配成功
                        return true;
                    }
                } else if (SYMBOL_JING.equals(subKey[len2 - 1])) {
                    // 从前往后比
                    for (i = 0; i < Math.min(len1, len2); i++) {
                        if (!subKey[i].equals(routingKeys[i])) {
                            break;
                        }
                    }
                    if (SYMBOL_JING.equals(subKey[i])) {
                        // 当前键匹配成功
                        return true;
                    }
                }
            } else {
                boolean flag = true;
                if (len1 == len2) {
                    for (int i = 0; i < len1; i++) {
                        if (!SYMBOL_STAR.equals(subKey[i]) && !routingKeys[i].equals(subKey[i])) {
                            flag = false;
                            // 匹配失败
                            break;
                        }
                    }
                    if (flag) {
                        return true;
                    }
                }
            }

        }
        return false;
    }

    private static boolean checkOnlyOne(String str) {
        return str.indexOf(SYMBOL_JING) == str.lastIndexOf(SYMBOL_JING);
    }
}
